#include "COUNT.h"

COUNT_T* COUNT_t;


//************************************
// Method:    	CALCU_SAMA					//< SAMA运算函数
// Programmer:  lww
// Time:		2018/11/16
// Returns:   	bool						//< 成功：true；失败：false
// Parameter: 	Model_Base_t * arg			//< 模块参数结构体指针
// Parameter: 	float dt					//< 运算周期
// Parameter: 	bool * DI					//< 数字量输入值数组指针
// Parameter: 	bool * DO					//< 数字量输出值数组指针
// Parameter: 	bool * AI					//< 模拟量输入值数组指针
// Parameter: 	bool * AO					//< 模拟量输出值数组指针
//************************************
bool CALCU_SAMA(COUNT)(Model_Base_t* arg, float dt, bool* DI, bool* DO, float* AI, float* AO)
{
	/****************变量定义区开始**************/
	/*<<<<<定义输入变量>>>>>*/
	bool CP;						//< 时钟脉冲信号
	bool Rd;						//< 复位输入
	/*<<<<<<<<<<<<<<<<<<<<<<*/

	/*<<<<<定义输出变量>>>>>*/
	//int Count_Num = 0;					//< 计数值							//< duan0829 将该变量设计为中间变量
	bool Finsh_Flg = false;				//< 计数完成标志
	/*<<<<<<<<<<<<<<<<<<<<<<*/

	/*<<<<<定义参数变量>>>>>*/
	COUNT_TOUGH_TYPE Tough_Type;			//< 触发方式
	COUNT_DIRECTION_TYPE Direction_Type;	//< 计数方向
	int max_count_num;						//< 计数器最大计数次数
	/*<<<<<<<<<<<<<<<<<<<<<<*/

	/*<<<<<定义中间变量>>>>>*/
	bool* CP_Last;					//< 上一时刻时钟脉冲信号
	int* Count_Num;					//< 计数值									//< duan0829
	bool* Init_Flag;				//< 初始化标志								//< duan0829
	/*<<<<<<<<<<<<<<<<<<<<<<*/

	/****************变量定义区结束**************/

	NAME(COUNT)* Obj = (NAME(COUNT)*)arg;

	/****************变量赋值**************/
	/*<<<<<输入变量赋值>>>>>*/
	CP = DI[0];
	Rd = DI[1];
	/*<<<<<<<<<<<<<<<<<<<<<<*/

	/*<<<<<参数变量赋值>>>>>*/
	Tough_Type = Obj->Par.Tough_Type;
	Direction_Type = Obj->Par.Direction_Type;
	max_count_num = Obj->Par.max_count_num;
	/*<<<<<<<<<<<<<<<<<<<<<<*/

	/*<<<<<中间变量赋值（由于中间变量属于静态变量，其数值要随运算而更新，
	因此此处建议将中间变量的地址赋值给相应变量，省去了运算完成后再次赋值
	给中间变量的过程）>>>>>*/
	CP_Last = &(Obj->Sta.CP_Last);
	Count_Num = &(Obj->Sta.Count_Num);
	Init_Flag = &(Obj->Sta.Init_Flag);
	/*<<<<<<<<<<<<<<<<<<<<<<*/
	/**************变量赋值结束************/

	/********************************************/
	/**************算法功能实现开始**************/
	/********************************************/
	
	if(Init_Flag[0]==false)
	{
		switch (Direction_Type) {
		case FORWARD: Count_Num[0] = 0; break;
		case BACKWARD:	Count_Num[0] = max_count_num; break;
		}
		Finsh_Flg = false;

		Init_Flag[0] = true;

	}

	if (Rd == true)
	{
		switch (Direction_Type) {
		case FORWARD: Count_Num[0] = 0; break;
		case BACKWARD:	Count_Num[0] = max_count_num; break;
		}
		Finsh_Flg = false;														//< duan0829
	}
	else
	{
		switch (Tough_Type) {
		case COUNT_TOUGH_UP:
			if (CP == true && CP_Last[0] == false)
			{
				switch (Direction_Type) {
					/*case FORWARD: Count_Num[0] = (int)(Obj->Base.Out.AO[0] + 1); break;
					case BACKWARD:	Count_Num[0] = (int)(Obj->Base.Out.AO[0] - 1); break;*/
				case FORWARD: Count_Num[0] += 1; break;											//< duan 191016 修改
				case BACKWARD:	Count_Num[0] -= 1; break;
				}
			}
			break;
		case COUNT_TOUGH_DOWN:
			if (CP == false && CP_Last[0] == true)
			{
				switch (Direction_Type) {
					/*case FORWARD: Count_Num[0] = (int)(Obj->Base.Out.AO[0] + 1); break;
					case BACKWARD:	Count_Num[0] = (int)(Obj->Base.Out.AO[0] - 1); break;*/
				case FORWARD: Count_Num[0] += 1; break;
				case BACKWARD:	Count_Num[0] -= 1; break;
				}
			}
			break;
		case COUNT_TOUGH_ANY:
			if (CP != CP_Last[0])
			{
				switch (Direction_Type) {
				/*case FORWARD: Count_Num[0] = (int)(Obj->Base.Out.AO[0] + 1); break;
				case BACKWARD:	Count_Num[0] = (int)(Obj->Base.Out.AO[0] - 1); break;*/
				case FORWARD: Count_Num[0] += 1; break;
				case BACKWARD:	Count_Num[0] -= 1; break;
				}
			}
			break;
		}
	}
	if ((Direction_Type == FORWARD && Count_Num[0] == max_count_num) || (Direction_Type == BACKWARD && Count_Num[0] == 0))
		Finsh_Flg = true;

	if (Count_Num[0] < 0)
		Count_Num[0] = max_count_num - 1;
		/*Count_Num[0] = max_count_num;*/							//< duan 191016修改
	else if (Count_Num[0] > max_count_num)
		Count_Num[0] = 1;
		/*Count_Num[0] = 0;*/

	CP_Last[0] = CP;
	/********************************************/
	/**************算法功能实现结束**************/
	/********************************************/

	/****************运算结果输出**************/
	DO[0] = Finsh_Flg;
	AO[0] = (float)Count_Num[0];
	//< printf("the num is %f \r\n", AO[0]);
	/**************运算结果输出完毕************/
	return true;
}



//************************************
// Method:    	BCPARA						//< 广播SAMA参数变量函数（无参数需要广播的模块直接将BCPara函数设置为NULL即可）
// Programmer:  lww
// Time:		2018/11/16
// Returns:   	int							//< 成功：返回打包字节个数；失败：返回0
// Parameter: 	Model_Base_t * arg			//< 模块参数结构体指针
// Parameter: 	void ** Data				//< 广播SAMA参数的数据包的指针
//************************************
int BC_PARA(COUNT)(Model_Base_t* arg, void** Data)
{
	NAME(COUNT)* Obj = (NAME(COUNT)*)arg;
	BC_PARA_PUBLIC(Obj);
	return 0;
}



//************************************
// Method:    	BAK_STA							//< 备份SAMA运算中间参数
// Programmer:  lww
// Time:		2018/11/16
// Returns:   	int								//< 成功：返回打包字节个数；失败：返回0
// Parameter: 	Model_Base_t * arg				//< 指定模块类型链表的指针
// Parameter: 	void ** Data					//< 存放数据包当前指针位置的地址
//************************************
int BAK_STA(COUNT)(Model_Base_t* arg, void** Data)
{
	NAME(COUNT)* Obj = (NAME(COUNT)*)arg;
	BAK_STA_PRIVATE(Obj);
	return 0;
}



//************************************
// Method:    	ANA_STA							//< 解析备份的SAMA运算中间参数
// Programmer:  lww
// Time:		2018/11/16
// Returns:   	int								//< 成功：返回解析字节个数；失败：返回0
// Parameter: 	Model_Base_t * arg				//< 模块参数结构体指针
// Parameter: 	void ** Data					//< 存放数据包当前指针位置的地址
//************************************
int ANA_STA(COUNT)(Model_Base_t* arg, void** Data)
{
	NAME(COUNT)* Obj = (NAME(COUNT)*)arg;
	ANA_STA_PRIVATE(Obj);
	return 0;
}



//************************************
// Method:    	CHANGE_PAR				//< 在线修改模块参数函数
// Programmer:  lww
// Time:		2018/11/16
// Returns:   	int						//< 读取字节长度计数值
// Parameter: 	Model_Base_t* arg		//< 指定模块类型链表的指针
// Parameter: 	void** Data				//< 存放数据包当前指针位置的地址
//************************************
int CHANGE_PAR(COUNT)(Model_Base_t* arg, void** Data)
{
	int _iLen = 0;
	MEMREAD(((NAME(COUNT)*)arg)->Par, Data[0]);
	return _iLen;
}



//************************************
// Method:    	INIT_STAPAR						//< 初始化模块运算中间参数
// Programmer:  lww
// Time:		2018/11/16
// Parameter: 	Model_Base_t* arg				//< 模块参数结构体指针
//************************************
void INIT_STAPAR(COUNT)(Model_Base_t* arg)
{
	NAME(COUNT)* name = (NAME(COUNT)*)arg;
	/****************初始化中间变量结构体**************/
	memset(&(name->Sta), 0, sizeof(name->Sta));
	/**************初始化中间变量结构体结束************/

	/****************对中间变量结构体的相关参数进行赋值**************/
	name->Sta.CP_Last = name->Base.In.DI[2];
	/**************对中间变量结构体的相关参数进行赋值结束************/
}
